package com.buobao.oa.service;

import com.buobao.oa.dao.EmployeeDao;
import com.buobao.oa.dao.NoticeDao;
import com.buobao.oa.dao.OvertimeFormDao;
import com.buobao.oa.dao.ProcessFlowDao;
import com.buobao.oa.dto.OvertimeFormDto;
import com.buobao.oa.entity.Employee;
import com.buobao.oa.entity.Notice;
import com.buobao.oa.entity.OvertimeForm;
import com.buobao.oa.entity.ProcessFlow;
import com.buobao.oa.utils.MybatisUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

public class OvertimeFormService {

    public OvertimeForm createOvertimeForm(OvertimeForm overtimeForm) {
        OvertimeForm result = (OvertimeForm) MybatisUtils.executeUpdate(sqlSession -> {
            EmployeeDao employeeDao = sqlSession.getMapper(EmployeeDao.class);
            Employee employee = employeeDao.selectByEmployeeId(overtimeForm.getEmployeeId());
            if (employee.getLevel() == 8) {
                //8级员工无需审批
                overtimeForm.setState("approved");
            } else {
                overtimeForm.setState("processing");
            }
            OvertimeFormDao overtimeFormDao = sqlSession.getMapper(OvertimeFormDao.class);
            overtimeFormDao.insert(overtimeForm);

            NoticeDao noticeDao = sqlSession.getMapper(NoticeDao.class);

            ProcessFlowDao processFlowDao = sqlSession.getMapper(ProcessFlowDao.class);
            ProcessFlow processFlow = new ProcessFlow();
            processFlow.setFormId(overtimeForm.getFormId());
            processFlow.setOperatorId(overtimeForm.getEmployeeId());
            processFlow.setAction("apply");
            processFlow.setCreateTime(new Date());
            processFlow.setOrder(1);
            processFlow.setState("complete");
            processFlow.setIsLast(0);
            processFlowDao.insert(processFlow);

            if (employee.getLevel() <= 7) {
                //生成提交消息
                Notice notice = new Notice();
                notice.setCreateTime(new Date());
                notice.setContent("您已提交加班申请单，等待上级审批");
                notice.setReceiverId(overtimeForm.getEmployeeId());
                noticeDao.insert(notice);

                Employee leader = employeeDao.selectLeader(employee);
                ProcessFlow processFlow1 = new ProcessFlow();
                processFlow1.setFormId(overtimeForm.getFormId());
                processFlow1.setOperatorId(leader.getEmployeeId());
                processFlow1.setAction("audit");
                processFlow1.setCreateTime(new Date());
                processFlow1.setOrder(2);
                processFlow1.setState("processing");
                long diff = overtimeForm.getEndTime().getTime() - overtimeForm.getStartTime().getTime();
                if (employee.getLevel() < 7 && diff / (1000 * 60 * 60) * 1f > BusinessConstants.MANAGER_AUDIT_HOURS) {
                    processFlow1.setIsLast(0);
                    Employee manager = employeeDao.selectLeader(leader);
                    ProcessFlow processFlow2 = new ProcessFlow();
                    processFlow2.setFormId(overtimeForm.getFormId());
                    processFlow2.setOperatorId(manager.getEmployeeId());
                    processFlow2.setCreateTime(new Date());
                    processFlow2.setAction("audit");
                    processFlow2.setState("ready");
                    processFlow2.setOrder(3);
                    processFlow2.setIsLast(1);
                    processFlowDao.insert(processFlow2);
                } else {
                    processFlow1.setIsLast(1);
                }
                processFlowDao.insert(processFlow1);

                //生成上级审批消息
                Notice notice1 = new Notice();
                notice1.setCreateTime(new Date());
                notice1.setContent("您有一条来自["+employee.getName()+"]的加班单，请尽快审批");
                notice1.setReceiverId(leader.getEmployeeId());
                noticeDao.insert(notice1);
            } else {
                ProcessFlow processFlow1 = new ProcessFlow();
                processFlow1.setFormId(overtimeForm.getFormId());
                processFlow1.setOperatorId(employee.getEmployeeId());
                processFlow1.setAction("audit");
                processFlow1.setResult("approved");
                processFlow1.setReason("自动通过");
                processFlow1.setCreateTime(new Date());
                processFlow1.setAuditTime(new Date());
                processFlow1.setState("complete");
                processFlow1.setOrder(2);
                processFlow1.setIsLast(1);
                processFlowDao.insert(processFlow1);

                //生成自动审批消息
                Notice notice1 = new Notice();
                notice1.setCreateTime(new Date());
                notice1.setContent("您的加班审批单已自动审批通过");
                notice1.setReceiverId(employee.getEmployeeId());
                noticeDao.insert(notice1);
            }
            return overtimeForm;
        });

        return result;
    }

    public List<OvertimeFormDto> selectFormByEmployee(Long employeeId){
        return (List<OvertimeFormDto>) MybatisUtils.executeQuery(sqlSession -> {
            OvertimeFormDao overtimeFormDao = sqlSession.getMapper(OvertimeFormDao.class);
            return overtimeFormDao.selectFormByEmployeeId(employeeId);
        });
    }

    public Page<OvertimeForm> selectSelfByEmployeeId(Long employeeId, int page, int limit) {
        return (Page<OvertimeForm>) MybatisUtils.executeQuery(sqlSession -> {
            PageHelper.startPage(page,limit);
            OvertimeFormDao overtimeFormDao = sqlSession.getMapper(OvertimeFormDao.class);
            return overtimeFormDao.selectSelfByEmployeeId(employeeId);
        });
    }

    public OvertimeForm selectFormById(Long formId) {
        return (OvertimeForm) MybatisUtils.executeQuery(sqlSession -> {
            OvertimeFormDao overtimeFormDao = sqlSession.getMapper(OvertimeFormDao.class);
            return overtimeFormDao.selectFormById(formId);
        });
    }

    public void update(OvertimeForm overtimeForm) {
        MybatisUtils.executeUpdate(sqlSession -> {
            OvertimeFormDao overtimeFormDao = sqlSession.getMapper(OvertimeFormDao.class);
            overtimeFormDao.update(overtimeForm);
            return null;
        });
    }

    public void audit(Long formId,String reason,String result){
        MybatisUtils.executeUpdate(sqlSession -> {
            OvertimeFormDao overtimeFormDao = sqlSession.getMapper(OvertimeFormDao.class);
            EmployeeDao employeeDao = sqlSession.getMapper(EmployeeDao.class);
            OvertimeForm overtimeForm = overtimeFormDao.selectFormById(formId);
            Employee employee = employeeDao.selectByEmployeeId(overtimeForm.getEmployeeId());

            //当前flow
            ProcessFlowDao processFlowDao = sqlSession.getMapper(ProcessFlowDao.class);
            ProcessFlow currentFlow = processFlowDao.selectProcessingByFormId(overtimeForm.getFormId());
            currentFlow.setResult(result);
            currentFlow.setReason(reason);
            currentFlow.setState("complete");
            processFlowDao.update(currentFlow);

            Employee currentOperator = employeeDao.selectByEmployeeId(currentFlow.getOperatorId());

            NoticeDao noticeDao = sqlSession.getMapper(NoticeDao.class);

            //生成当前审批人通知
            Notice notice = new Notice();
            notice.setCreateTime(new Date());
            notice.setContent("您已审批 "+ ("refused".equals(result)?"拒绝 ":"通过 ")+"["+employee.getName()+"]的加班申请单");
            notice.setReceiverId(currentFlow.getOperatorId());
            noticeDao.insert(notice);

            //生成申请人通知
            Notice notice1 = new Notice();
            notice1.setCreateTime(new Date());
            notice1.setContent("您的加班申请单已被["+currentOperator.getName()+"] 审批 "+ ("refused".equals(result)?"拒绝 ":"通过 "));
            notice1.setReceiverId(overtimeForm.getEmployeeId());
            noticeDao.insert(notice1);

            if (currentFlow.getIsLast()==1) {
                //如果是最后一步审批则更新表单状态
                overtimeForm.setState(result);
                overtimeFormDao.update(overtimeForm);
            } else {
                ProcessFlow nextFlow = processFlowDao.selectNextByFormIdAndOrder(new HashMap<String,Object>(){
                    {
                        put("formId",overtimeForm.getFormId());
                        put("order",currentFlow.getOrder()+1);
                    }
                });
                if ("refused".equals(result)) {
                    nextFlow.setReason("自动拒绝");
                    nextFlow.setResult(result);
                    nextFlow.setState("complete");
                    processFlowDao.update(nextFlow);

                    overtimeForm.setState(result);
                    overtimeFormDao.update(overtimeForm);
                } else {
                    nextFlow.setState("processing");
                    processFlowDao.update(nextFlow);

                    //生成下一级审批人通知
                    Notice notice2 = new Notice();
                    notice2.setCreateTime(new Date());
                    notice2.setContent("您有一条来自["+employee.getName()+"]的加班单，请尽快审批");
                    notice2.setReceiverId(nextFlow.getOperatorId());
                    noticeDao.insert(notice2);
                }
            }

            return null;
        });
    }
}
